import './markdownItEditable.css';

/**
 * markdown-it 通用编辑插件
 * 为所有块级元素和部分行内元素添加编辑功能
 * 直接在原始HTML元素上添加编辑属性，避免包装div容器
 */

/**
 * 组件信息存储（使用 WeakMap 避免内存泄漏）
 * 注意：这里只是临时存储，真正的存储在 DOM 元素的 dataset 中
 */
const componentInfoStore = new WeakMap();

/**
 * 生成唯一的组件ID
 */
function generateComponentId() {
  return 'editable-' + Math.random().toString(36).substr(2, 9);
}

/**
 * 获取模块源代码和位置信息
 * 正确处理不同的换行符（\n, \r\n）
 */
function getModuleSourceCode(state, token) {
  if (!state || !state.src || !token.map) {
    return { originalMarkdown: '', tokenStart: 0, tokenEnd: 0 };
  }
  
  const source = state.src;
  const [startLine, endLine] = token.map;
  
  // 使用正则表达式分割，保留换行符信息
  // 这样可以正确处理 \n, \r\n, \r 等不同的换行符
  const lines = source.split(/(\r?\n)/);
  
  let tokenStart = 0;
  let tokenEnd = 0;
  let currentLine = 0;
  
  // 计算起始位置
  for (let i = 0; i < lines.length && currentLine < startLine; i++) {
    tokenStart += lines[i].length;
    // 只在遇到换行符时增加行号
    if (lines[i].match(/\r?\n/)) {
      currentLine++;
    }
  }
  
  // 重置行号计数器
  currentLine = 0;
  
  // 计算结束位置
  for (let i = 0; i < lines.length && currentLine < endLine; i++) {
    tokenEnd += lines[i].length;
    // 只在遇到换行符时增加行号
    if (lines[i].match(/\r?\n/)) {
      currentLine++;
    }
  }
  
  // 调整位置，确保在有效范围内
  tokenStart = Math.max(0, tokenStart);
  tokenEnd = Math.min(source.length, tokenEnd);
  
  const originalMarkdown = tokenStart < tokenEnd ? source.substring(tokenStart, tokenEnd) : '';
  
  return { originalMarkdown, tokenStart, tokenEnd };
}

/**
 * 为HTML元素添加编辑属性
 */
function addEditableAttributes(html, componentType, state, token) {
  // 检查是否已经是可编辑元素，避免重复添加
  if (html.includes('data-editable="true"')) {
    return html;
  }
  
  const componentId = generateComponentId(componentType);
  
  // 获取源代码和位置信息
  const { originalMarkdown, tokenStart, tokenEnd } = getModuleSourceCode(state, token, componentType);
  
  // 只存储位置信息，编辑时从最新内容提取
  const positionInfo = `${tokenStart},${tokenEnd}`;
  
  // 改进的正则表达式：匹配第一个HTML标签，即使有前导空白
  // 移除 onclick 属性，改用事件委托
  return html.replace(/^(\s*<\w+)/, `$1 data-editable="true" data-component-id="${componentId}" data-component-type="${componentType}" data-position="${positionInfo}"`);
}

/**
 * 通用编辑插件主函数
 */
export default function markdownItEditable(md) {
  // 使用 core ruler 保存 state 到 env
  md.core.ruler.push('save_state_to_env', function(state) {
    state.env.markdownState = state
  })
  
  // 定义需要单独编辑的元素类型（基于实际可用的token类型）
  const editableTokenTypes = [
    'code_block',               // 代码块
    'math_block',               // 数学公式块
    'image',                    // 图片
    'html_block',               // HTML块
    'html_inline',              // 行内HTML
    'container_info_open',      // 信息容器
    'container_warning_open',   // 警告容器
    'container_danger_open',    // 危险容器
    'container_cell_open'       // 单元格容器
  ];
  
  // 定义不需要单独编辑的行内元素（这些应该包含在段落中一起编辑）
  const inlineElements = [
    'code_inline',      // 行内代码
    'math_inline',      // 行内数学公式
    'em_open',          // 斜体
    'strong_open',      // 粗体
    's_open',          // 删除线
    'link_open',       // 链接
    'footnote_ref',     // 脚注引用
    'emoji',           // 表情符号
    'hardbreak',       // 硬换行
    'softbreak'        // 软换行
  ];
  
  // 保存原始的fence渲染规则
  const defaultFenceRender = md.renderer.rules.fence || function(tokens, idx, options, env, self) {
    return self.renderToken(tokens, idx, options);
  };

  // 重写fence渲染规则
  md.renderer.rules.fence = (tokens, idx, options, env, self) => {
    const token = tokens[idx];
    const code = token.content.trim();
    const info = token.info.trim();

    // 从 env 获取 state
    const state = env.markdownState || null;

    // 先调用默认渲染器
    let result = defaultFenceRender(tokens, idx, options, env, self);

    // 检查是否是echarts、dataset或mermaid容器，直接给容器添加编辑属性
    if (result.includes('echarts-container')) {
      result = addEditableAttributes(result, 'echarts', state, token);
    } else if (result.includes('dataset-container')) {
      result = addEditableAttributes(result, 'dataset', state, token);
    } else if (result.includes('mermaid')) {
      result = addEditableAttributes(result, 'mermaid', state, token);
    } else {
      // 对于普通代码块，添加编辑属性
      result = addEditableAttributes(result, 'code', state, token);
    }

    return result;
  };

  // 为需要单独编辑的元素类型添加编辑功能
  editableTokenTypes.forEach(tokenType => {
    if (!md.renderer.rules[tokenType]) {
      // 如果该token类型没有默认渲染规则，跳过
      return;
    }
    
    const defaultRender = md.renderer.rules[tokenType];
    
    md.renderer.rules[tokenType] = (tokens, idx, options, env, self) => {
      const token = tokens[idx];
      
      // 根据token类型确定组件类型
      let componentType = token.tag || tokenType;
      if (tokenType === 'math_block' || tokenType === 'math_inline') {
        componentType = 'math';
      } else if (tokenType === 'image') {
        componentType = 'img';
      } else if (tokenType === 'container_info_open') {
        componentType = 'info';
      } else if (tokenType === 'container_warning_open') {
        componentType = 'warning';
      } else if (tokenType === 'container_danger_open') {
        componentType = 'danger';
      } else if (tokenType === 'container_cell_open') {
        componentType = 'cell';
      }
      
      // 从 env 获取 state
      const state = env.markdownState || null;
      
      // 调用默认渲染器
      let html = defaultRender(tokens, idx, options, env, self);
      
      // 添加编辑属性
      html = addEditableAttributes(html, componentType, state, token);
      
      return html;
    };
  });
  
  // 为标题添加编辑功能
  const headingTokenTypes = ['heading_open'];
  headingTokenTypes.forEach(tokenType => {
    // 创建默认渲染规则
    const defaultRender = md.renderer.rules[tokenType] || function(tokens, idx, options, env, self) {
      return self.renderToken(tokens, idx, options);
    };
    
    md.renderer.rules[tokenType] = (tokens, idx, options, env, self) => {
      const token = tokens[idx];
      const html = defaultRender(tokens, idx, options, env, self);
      
      // 确定标题级别
      let componentType = 'p'; // 默认段落
      if (token.tag === 'h1') componentType = 'h1';
      else if (token.tag === 'h2') componentType = 'h2';
      else if (token.tag === 'h3') componentType = 'h3';
      else if (token.tag === 'h4') componentType = 'h4';
      else if (token.tag === 'h5') componentType = 'h5';
      else if (token.tag === 'h6') componentType = 'h6';
      
      // 从 env 获取 state
      const state = env.markdownState || null;
      
      return addEditableAttributes(html, componentType, state, token);
    };
  });
  
  // 为段落添加编辑功能
  const paragraphTokenTypes = ['paragraph_open'];
  paragraphTokenTypes.forEach(tokenType => {
    // 创建默认渲染规则
    const defaultRender = md.renderer.rules[tokenType] || function(tokens, idx, options, env, self) {
      return self.renderToken(tokens, idx, options);
    };
    
    md.renderer.rules[tokenType] = (tokens, idx, options, env, self) => {
      const token = tokens[idx];
      const html = defaultRender(tokens, idx, options, env, self);
      
      // 段落类型
      const componentType = 'p';
      
      // 从 env 获取 state
      const state = env.markdownState || null;
      
      return addEditableAttributes(html, componentType, state, token);
    };
  });
  
  // 为列表容器添加编辑功能
  const listContainerTokenTypes = ['bullet_list_open', 'ordered_list_open'];
  listContainerTokenTypes.forEach(tokenType => {
    // 创建默认渲染规则
    const defaultRender = md.renderer.rules[tokenType] || function(tokens, idx, options, env, self) {
      return self.renderToken(tokens, idx, options);
    };
    
    md.renderer.rules[tokenType] = (tokens, idx, options, env, self) => {
      const token = tokens[idx];
      const html = defaultRender(tokens, idx, options, env, self);
      
      // 确定列表类型
      let componentType = 'ul'; // 默认无序列表
      if (tokenType === 'ordered_list_open') {
        componentType = 'ol';
      }
      
      // 从 env 获取 state
      const state = env.markdownState || null;
      
      return addEditableAttributes(html, componentType, state, token);
    };
  });
  
  // 为表格容器添加编辑功能
  const tableContainerTokenTypes = ['table_open'];
  tableContainerTokenTypes.forEach(tokenType => {
    // 创建默认渲染规则
    const defaultRender = md.renderer.rules[tokenType] || function(tokens, idx, options, env, self) {
      return self.renderToken(tokens, idx, options);
    };
    
    md.renderer.rules[tokenType] = (tokens, idx, options, env, self) => {
      const token = tokens[idx];
      const html = defaultRender(tokens, idx, options, env, self);
      
      // 表格类型
      const componentType = 'table';
      
      // 从 env 获取 state
      const state = env.markdownState || null;
      
      return addEditableAttributes(html, componentType, state, token);
    };
  });
  
  // 对于不需要单独编辑的行内元素，跳过处理
  inlineElements.forEach(tokenType => {
    if (md.renderer.rules[tokenType]) {
      // 静默跳过
    }
  });
}